#pragma once
#include <iostream>
#include <unistd.h>
#include <cstring>
#include "Log.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include"InetAddr.hpp"
//服务器要绑定自己的ip与port
enum
{
    SOCKETERROR = 1,
    BINDERROR,
};
class UdpSever
{
public:
    UdpSever(uint16_t port) : _port(port), _isrunning(false)
    {
    }
    void InitSocket()
    {
        // 1.创建套接字，并返回文件描述符sockfd，
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0) // 获取失败
        {
            Log(FATAL, "server sockfd get fail,[%s,%d]", strerror(errno), errno);
            exit(SOCKETERROR);
        }
        Log(DEBUG, "sever sockfd get success...");

        // 2.获取IP与port的网络字节序
        struct sockaddr_in local;           // 创建套接字地址结构
        memset(&local, 0, sizeof(local));   // 清空
        local.sin_family = AF_INET;         // 地址族，IPv4
        local.sin_port = htons(_port);      // 端口号，转为网络字节序
        local.sin_addr.s_addr = INADDR_ANY; // IP地址设为0,以监听所有网络接口的信号

        // 3.绑定套接字描述符与套接字地址结构
        int n = bind(_sockfd, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            Log(FATAL, "server socket bind fail,[%s,%d]", strerror(errno), errno);
            exit(BINDERROR);
        }
        Log(DEBUG, "sever socket bind success...");
    }
    // 启动服务器
    void StartUdpServer()
    {
        Log(DEBUG, "UdpSever already start success...");
        _isrunning = true; // 运行状态改为true
        while (true)       // 服务器死循环
        {
            // 服务器需要先收到消息
            char buffer[1024];       // 存储接收到的消息
            struct sockaddr_in peer; // 存储客户端的套接字信息
            socklen_t len = sizeof(peer);
            // 接收消息
            ssize_t n=recvfrom(_sockfd, buffer, sizeof(buffer)-1, 0, (sockaddr *)&peer, &len);
            if(n>0)
            {
                buffer[n]=0;
            }
            // 将远端机器的IP与port转换出来
            InetAddr addr(peer);
            std::string ip=addr.IP();
            uint16_t port=addr.port();

            Log(INFO, "UdpSever get a message from [%s,%d] : %s",  ip.c_str(), port,buffer);
            // 发送消息
            sendto(_sockfd, buffer, sizeof(buffer), 0, (sockaddr *)&peer, len);
            Log(INFO, "UdpSever send to [%s,%d]: %s", ip.c_str(), port, buffer);
        }
        _isrunning = false;
    }
    ~UdpSever()
    {
    }

private:
    int _sockfd;     // 套接字描述符
    uint16_t _port;  // 端口号，需传入
    bool _isrunning; // 运行状态，初始为false
};